package org.csu.softwaremetrics_demo.entity.entry;

import com.google.common.collect.Lists;
import org.csu.softwaremetrics_demo.entity.common.LKMetricSingleClass;
import org.csu.softwaremetrics_demo.entity.executor.MetricsExecutor;
import org.csu.softwaremetrics_demo.entity.result.impl.LKMetricResult;
import org.csu.softwaremetrics_demo.metric.Metric;
import org.csu.softwaremetrics_demo.metric.lk.*;
import org.csu.softwaremetrics_demo.util.ColorLoggerUtils;
import org.csu.softwaremetrics_demo.util.FileUtils;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.ASTParser;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;

/**
 * @Description: LK类用于计算指定路径下Java代码的LK度量指标。
 * LK度量指标是一种软件度量方法，用于衡量软件的复杂性、可维护性等。
 * @Author: Jukomu
 * @Package: org.csu.softwaremetrics_demo.entity.entry
 * @Project: SoftwareMetrics_demo
 * @name: LK
 * @Date: 2025/4/6-19:50
 * @Filename: LK
 */
public class LK {
    private static final int MAX_AT_ONCE;

    static {
        String jdtMax = System.getProperty("jdt.max");
        if (jdtMax != null) {
            MAX_AT_ONCE = Integer.parseInt(jdtMax);
        } else {
            long maxMemory = Runtime.getRuntime().maxMemory() / (1 << 20); // in MiB

            if (maxMemory >= 2000) {
                MAX_AT_ONCE = 400;
            } else if (maxMemory >= 1500) {
                MAX_AT_ONCE = 300;
            } else if (maxMemory >= 1000) {
                MAX_AT_ONCE = 200;
            } else if (maxMemory >= 500) {
                MAX_AT_ONCE = 100;
            } else {
                MAX_AT_ONCE = 25;
            }
        }
    }

    public List<Callable<Metric>> pluggedMetrics;
    private static ColorLoggerUtils logger = ColorLoggerUtils.getLogger(CK.class);

    public LK() {
        this.pluggedMetrics = new ArrayList<>();
    }


    /**
     * 计算指定路径下Java代码的LK度量指标
     * 处理步骤：
     * 1. 获取所有Java源文件
     * 2. 创建AST解析器
     * 3. 按批次处理源文件
     * 4. 收集度量结果
     *
     * @param path Java源代码路径
     * @return 包含所有度量结果的报告
     */
    public LKMetricResult calculate(String path) {
        // 获取文件
        String[] srcDirs = FileUtils.getAllDirs(path);
        String[] javaFiles = FileUtils.getAllJavaFiles(path);

        MetricsExecutor<LKMetricResult, LKMetricSingleClass> storage = new MetricsExecutor<>(this::metrics, LKMetricResult.class);

        // 分为很多个partitions
        List<List<String>> partitions = Lists.partition(Arrays.asList(javaFiles), MAX_AT_ONCE);

        // 分为多个partitions进行度量
        for (List<String> partition : partitions) {
            ASTParser parser = ASTParser.newParser(AST.JLS8);

            parser.setResolveBindings(true);
            parser.setBindingsRecovery(true);

            Map<?, ?> options = JavaCore.getOptions();
            JavaCore.setComplianceOptions(JavaCore.VERSION_1_8, options);
            parser.setCompilerOptions(options);
            parser.setEnvironment(null, srcDirs, null, true);
            parser.createASTs(partition.toArray(new String[partition.size()]), null, new String[0], storage, null);
        }

        LKMetricResult result = storage.getResult();
        result.calculateSI();
        return result;
    }

    private List<Metric<LKMetricSingleClass>> metrics() {
        List<Metric<LKMetricSingleClass>> all = defaultMetrics();
        return all;
    }

    /**
     * 获取默认的LK度量指标列表
     * 包括核心的LK度量指标和扩展指标
     *
     * @return 度量指标列表
     */
    private List<Metric<LKMetricSingleClass>> defaultMetrics() {
        return new ArrayList<>(Arrays.asList(new NOF(), new NOM(), new NOA(), new NOO(), new DIT()));
    }
}
